﻿namespace Bildverarbeitung.CGFilter
{
    using System;
    using System.Drawing;
    using Bildverarbeitung;
    using AForge;
    using AForge.Imaging;
    using AForge.Imaging.Filters;
    using AForge.Math.Geometry;
    using System.Drawing.Imaging;
using System.Collections.Generic;

    /// <summary>
    /// 
    /// </summary>
    public class RichardtManuelFilter : Bildverarbeitung.IFilter
    {
        /// <summary>
        /// Gets the summerized difference from average of all images.
        /// </summary>
        /// <param name="images">Given images.</param>
        /// <returns>The summerized difference.</returns>
        public Bitmap GetImageWithDoor(Bitmap img)
        {
            BitmapData bitmapData = img.LockBits(
                            new Rectangle(0, 0, img.Width, img.Height),
                            ImageLockMode.ReadWrite, img.PixelFormat);
            UnmanagedImage image = new UnmanagedImage(bitmapData);

            /*  Anmerkungen des Autors:
             *  Ich habe nichts dagegen, wenn Ihr euch meinen Code anseht oder Teile daraus verwendet.
             *  Aber eine 1:1-Kopie, wo lediglich die Namen der Variablen verändert werden, ist
             *  schon sehr dreist!
             */
            //Ergebnisbild mit Saturation erzeugen
            #region Ergebnisbild setzen
            //Kopie des Bildes erzeugen
            UnmanagedImage resultImage = image.Clone();
            //Saturation auf 20% und Ergebnisbild setzen
            SaturationCorrection sat = new SaturationCorrection(-0.8f);
            sat.ApplyInPlace(resultImage);
            #endregion

            //Orginalbild in Graustufen wegen CannyEdge danach Threshold
            //Input=Orginalbild; Output=Orginalbild
            #region Bildvorverarbeitung
            //Graustufen
            Grayscale gray = new Grayscale(0.2125, 0.7154, 0.0721);
            image = gray.Apply(image);
            //CannyEdgeFilter (Kanten markieren)
            CannyEdgeDetector filter = new CannyEdgeDetector(20, 25);
            filter.ApplyInPlace(image);
            //Besserer Kontrast
            Threshold th = new Threshold(20);
            th.ApplyInPlace(image);
            #endregion

            //Start BlobCounter zur Markierung von Flächen und Eckpunkten
            //Input=Bildvorverarbeitung; Output=Ergebnisbild
            #region BlobCounter
            BlobCounter bc = new BlobCounter();
            bc.FilterBlobs = true;
            bc.MinHeight = 100;
            bc.MinWidth = 100;
            bc.MaxHeight = 800;
            bc.MaxWidth = 300;
            bc.ObjectsOrder = ObjectsOrder.Size;
            bc.ProcessImage(image);
            Blob[] blobCounter = bc.GetObjectsInformation();
            if (blobCounter.Length > 0)
            {
                //Größter vorkommender "Blob" in Ergebnisbild als Gelb markieren
                Drawing.FillRectangle(resultImage, blobCounter[0].Rectangle, Color.Yellow);
                Parallel.For(0, blobCounter.Length, i =>
                {
                    //Alle vorkommenden Eckpunkte in Rot markieren
                    Drawing.FillRectangle(resultImage, new Rectangle(blobCounter[i].Rectangle.X - 10, blobCounter[i].Rectangle.Y - 10, 20, 20), Color.Red);
                    Drawing.FillRectangle(resultImage, new Rectangle(blobCounter[i].Rectangle.X + blobCounter[i].Rectangle.Width - 10, blobCounter[i].Rectangle.Y - 10, 20, 20), Color.Red);
                    Drawing.FillRectangle(resultImage, new Rectangle(blobCounter[i].Rectangle.X - 10, blobCounter[i].Rectangle.Y + blobCounter[i].Rectangle.Height - 10, 20, 20), Color.Red);
                    Drawing.FillRectangle(resultImage, new Rectangle(blobCounter[i].Rectangle.X + blobCounter[i].Rectangle.Width - 10, blobCounter[i].Rectangle.Y + blobCounter[i].Rectangle.Height - 10, 20, 20), Color.Red);
                });
            }
            #endregion

            //SusanCorner anwenden (Zeichnet "schönere" Kanten)
            //Input=Ergebnisbild; Output=Ergebnisbild
            #region SusanCorner
            SusanCornersDetector susan = new SusanCornersDetector(20, 30);
            List<IntPoint> corners = susan.ProcessImage(resultImage);

            Parallel.For(0, corners.Count - 1, i =>
            {
                IntPoint p1 = new IntPoint((int)corners[i].X, (int)corners[i].Y);
                IntPoint p2 = new IntPoint((int)corners[i].X, (int)corners[i + 1].Y);

                if (p1.DistanceTo(p2) < 10)
                {
                    //Kanten im Ergebnisbild in Grün markieren
                    Drawing.FillRectangle(resultImage, new Rectangle(p1.X, p1.Y, 5, 5), Color.Green);
                }
            });
            #endregion

            return resultImage.ToManagedImage();
        }

        /// <summary>
        /// Return the author´s name
        /// Please use NachnameVorname (without spaces).
        /// </summary>
        /// <returns>author´s name</returns>
        public String GetName()
        {
            return ("RichardtManuel");
        }
    }
}
